package com.gomoney.auth.security.service;


import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.gomoney.auth.service.SysMenuService;
import com.gomoney.auth.mapper.SysUserMapper;
import com.gomoney.auth.model.SysUserDetail;
import com.gomoney.auth.security.constant.AuthConstant;
import com.gomoney.auth.service.SysCaptchaService;
import com.gomoney.auth.service.SysMenuService;
import com.gomoney.oauth2.common.entity.sys.SysMenu;
import com.gomoney.oauth2.common.entity.sys.SysUser;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.session.SessionRegistry;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.util.ObjectUtils;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

/**
 * @Description //TODO
 * @Author zhangyong
 * 我们自定义用户名和密码登录和数据库结合
 * @Date 2021/4/25 16:00
 **/
@Service
public class UserDetailsServiceImpl implements UserDetailsService {
    //前台用户数据库结合
    @Autowired
    private PasswordEncoder passwordEncoder;

    //后台用户数据库结合
    @Autowired
    private SysUserMapper sysUserMapper;

    @Autowired
    private SysMenuService menuService;

    @Autowired
    private SysCaptchaService sysCaptchaService;

    @Autowired
    private SessionRegistry sessionRegistry;

    /**
     * Locates the user based on the username. In the actual implementation, the search
     * may possibly be case sensitive, or case insensitive depending on how the
     * implementation instance is configured. In this case, the <code>UserDetails</code>
     * object that comes back may have a username that is of a different case than what
     * was actually requested..
     *
     * @param username the username identifying the user whose data is required.
     * @return a fully populated user record (never <code>null</code>)
     * @throws UsernameNotFoundException if the user could not be found or the user has no
     *                                   GrantedAuthority
     */
    //和数据库结合的真实登录
    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        String[] info = username.split(",");
        username = info[0];
        ServletRequestAttributes requestAttributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        //1.拿到request
        HttpServletRequest request = requestAttributes.getRequest();
        //2.拿到header数据
        String header = request.getHeader(AuthConstant.LOGIN_TYPE);
        if (StringUtils.isNotEmpty(header) && header.equals("login")) {
            boolean captcha = sysCaptchaService.validate(info[1], info[2]);
            if (!captcha) {
                return null;
            }
        }
        //用户已经登录则此次登录失败
/*        List<Object> o = sessionRegistry.getAllPrincipals();
        for ( Object principal : o) {
            if (principal.toString().equals(username)) {
                throw new SessionAuthenticationException("当前用户已经在线，登录失败！！！");
            }
        }*/
        //后台
        SysUser sysUser = sysUserMapper.selectOne(new LambdaQueryWrapper<SysUser>()
                .eq(SysUser::getUserName, username)
        );
        //封装权限
        if (!ObjectUtils.isEmpty(sysUser)) {
            Set<String> permsSet = new HashSet<>();
            List<SysMenu> menus = new ArrayList<>();
            //用户权限列表
            if (sysUser.getUserId().equals("06afa981-46e9-11e9-b7af-3c2c30a6698a")) {
                menus = menuService.findMenuForAll(1);
                permsSet = menuService.getAllPermissions(menus);
            } else {
                permsSet = menuService.getUserPermissions(sysUser.getUserId());
            }
            sysUser.setPermsSet(permsSet);
        }
        return new SysUserDetail(sysUser);
    }
}
